<?php


namespace app\controller\api;


use app\common\service\redis\PoolRedis;
use app\common\service\sms\AliSms;
use app\model\AdminParents;
use app\model\AdminParentsData;
use app\model\AdminStaff;
use app\model\AdminStudentParents;
use app\util\ReturnCode;
use app\util\Strs;
use app\util\Tools;
use think\facade\Db;
use think\facade\Log;
use think\facade\Validate;
use think\Response;

class Parents extends Base
{
    /**
     * @func login
     * @method POST
     * @desc 家长登录
     * @return Response
     * @Time: 2022/3/17 11:02
     */
    public function login(): Response {
        $phone  = input('post.phone');
        $code  = input('post.code/d');
        $device_id  = input('post.device_id/s', '');
        $device_name  = input('post.device_name/s', '');
        if (empty($phone) || !validatePhone($phone)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, '请输入正确的手机号');
        }
        if (!AliSms::check($phone, $code)) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '验证码错误');
        }
        $parent = (new AdminParents())->where('phone', $phone)->where('is_delete', 0)->find();
        if (!$parent) {
            return $this->buildFailed(ReturnCode::NOT_EXISTS, '账号不存在');
        }
        // 关联学生
        $joinStudents = AdminStudentParents::where('parent_id', $parent->id)->where('is_delete', 0)
            ->column('remark', 'status');

        if (!$joinStudents || isset($joinStudents[AdminStudentParents::AUDIT_PASS])) {
            //更新用户数据
            $parentData = $parent->parentData;
            $data = [];
            if ($parentData) {
                if (in_array($parentData->bind_device_status, [1, 2]) && $device_id && $parentData->last_login_device_id && $device_id != $parentData->last_login_device_id) {
                    return $this->buildFailed(ReturnCode::LOGIN_ERROR, '账号与绑定手机不符');
                }
                $parentData->login_times++;
                $parentData->last_login_ip = sprintf("%u", ip2long($this->request->ip()));
                $parentData->last_login_time = time();
                if (!in_array($parentData->bind_device_status, [1, 2]) && $device_id) {
                    $parentData->last_login_device_id = $device_id;
                    $parentData->last_login_device_name = $device_name;
                    $parentData->bind_device_status = 1;
                    $parentData->last_bind_device_time = time();
                }
                $parentData->save();
            } else {
                $data['login_times'] = 1;
                $data['parent_id'] = $parent->id;
                $data['last_login_ip'] = sprintf("%u", ip2long($this->request->ip()));
                $data['last_login_time'] = time();
                $data['last_login_device_id'] = $device_id;
                $data['last_login_device_name'] = $device_name;
                $data['bind_device_status'] = 1;
                $data['last_bind_device_time'] = time();
                AdminParentsData::create($data);
            }

            // 保存登录成功设备,30天
            $redis = PoolRedis::instance();
            $log_device_id = $redis->get('deviceUUID:staff'.$parent->id);
            // 已登录的设备下线,并且重新生成uuid
            if ($log_device_id && $device_id && $log_device_id != $device_id) {
                $redis->set('deviceUUID:staff'.$parent->uuid, 'offline');
                $parent->uuid = substr(Strs::uuid(), 1, -1);
                $parent->save();
            }
            // 更新登录信息
            $redis->set('deviceUUID:staff'.$parent->uuid, 'online', 30*86400);
            if ($device_id) {
                $redis->set('deviceUUID:staff'.$parent->id, $device_id, 30*86400);
            }

            return $this->buildSuccess([
                'uuid' => $parent->uuid
            ], '登录成功');
        } elseif (!isset($joinStudents[AdminStudentParents::AUDIT_WAITING])) {
            return $this->buildFailed(ReturnCode::AUDIT_FAILED, '账号审核拒绝', [
                'refuse_reason' => $joinStudents[AdminStudentParents::AUDIT_REFUSE],
                'uuid' => $parent->uuid
            ]);
        } else {
            return $this->buildFailed(ReturnCode::AUDIT_WAITING, '账号审核中');
        }
    }

    /**
     * @func apply
     * @method POST
     * @desc 家长提交审核
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Time: 2022/3/17 15:54
     */
    public function apply(): Response {
        $postData = input('post.');
        $validate = Validate::rule([
            'phone|手机号' => 'require|mobile',
            'name|姓名' => 'require|max:20',
            'sex|性别' => 'require',
            'students|学生' => 'require',
        ]);
        if (!$validate->check($postData)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $where = [
            ['phone', '=', $postData['phone']],
            ['is_delete', '=', 0],
        ];
        if (isset($postData['uuid']) && !empty($postData['uuid'])) {
            array_push($where, [
                'uuid', '<>', $postData['uuid']
            ]);
        }
        $exists = AdminParents::where($where)->find();
        if ($exists) {
            return $this->buildFailed(ReturnCode::DATA_EXISTS, '手机号已存在');
        }

        Db::startTrans();
        try {
            $students = is_array($postData['students']) ? $postData['students'] : json_decode($postData['students'], true);
            unset($postData['students']);
            $data = $postData;
            if (isset($postData['uuid']) && !empty($postData['uuid'])) {
                $parent = AdminParents::where('uuid', $postData['uuid'])
                    ->where('is_delete', 0)->find();
            } else {
                $data['password'] = Tools::userMd5(substr($postData['phone'], -6));
                $data['uuid'] = substr(Strs::uuid(), 1, -1);
                $parent = AdminParents::create($data);
            }

            foreach ($students as &$item) {
                $staff_id = AdminStaff::where('phone', $item['phone'])->where('is_delete', 0)->value('id');
                if (!$staff_id) {
                    Db::rollback();
                    return $this->buildFailed(ReturnCode::NOT_EXISTS, "手机号 {$item['phone']} 的学生不存在，请重新输入");
                }
                $item['parent_id'] = $parent->id;
                $item['staff_id'] = $staff_id;
            }
            $joinStudent = new AdminStudentParents();
            $joinStudent->saveAll($students);
            DB::commit();
        } catch (\Exception $e) {
            Log::error('家长新增事务失败：'.$e->getMessage());
            DB::rollback();
            return $this->buildFailed(ReturnCode::DB_SAVE_ERROR);
        }
        return $this->buildSuccess();
    }

    /**
     * @func account
     * @param uuid
     * @method GET
     * @desc 家长资料（个人、学生资料）
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Time: 2022/3/17 16:53
     */
    public function account(): Response {
        $uuid = $this->request->get('uuid');
        $parent = AdminParents::where('uuid', $uuid)->where('is_delete', 0)
            ->field('id,name,sex,phone,avatar_url,uuid')
            ->append(['student.school.name'])
            ->with(['student' => function($query) {
                $query->with('staff')->where('is_delete', 0)
                    ->withAttr('staff.avatar_url', function($value, $data) {
                        return $value ? $this->request->domain() .$value : '';
                    })
                    ->order('create_time', 'desc');
            }])
            ->find()->toArray();
        if (!$parent) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '账号不存在');
        }
        $parent['avatar_name'] = $parent['avatar_url'];
        $parent['avatar_url'] = $parent['avatar_url'] ? $this->request->domain() . $parent['avatar_url'] : '';
        return $this->buildSuccess($parent);
    }

    /**
     * @func addStudent
     * @method POST
     * @desc 家长添加学生
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Time: 2022/3/17 15:54
     */
    public function addStudent(): Response {
        $postData = input('post.');
        $validate = Validate::rule([
            'phone|手机号' => 'require|mobile',
            'school_id|学校ID' => 'require',
            'uuid|用户标识' => 'require',
        ]);
        if (!$validate->check($postData)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $parent = AdminParents::where('uuid', $postData['uuid'])->where('is_delete', 0)->find();
        if (!$parent) {
            return $this->buildFailed(ReturnCode::NOT_EXISTS, '账号不存在');
        }
        $joinStudent = AdminStudentParents::where('phone', $postData['phone'])
                ->where('parent_id', $parent->id)
                ->where('is_delete', 0)
                ->find();
        if ($joinStudent) {
            return $this->buildFailed(ReturnCode::DATA_EXISTS, '手机号已被绑定');
        }
        $student_id = AdminStaff::where('phone', $postData['phone'])
            ->where('type', AdminStaff::STUDENT)
            ->where('is_delete', 0)->value('id');
        if (!$student_id) {
            return $this->buildFailed(ReturnCode::DATA_EXISTS, '学生不存在');
        }
        $postData['parent_id'] = $parent->id;
        $postData['staff_id'] = $student_id;
        $res = AdminStudentParents::create($postData);
        if (!$res) {
            return $this->buildFailed(ReturnCode::DB_SAVE_ERROR);
        }
        return $this->buildSuccess();
    }

    /**
     * @func changeStatus
     * @method GET
     * @desc 学生状态修改
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Time: 2022/3/17 16:41
     */
    public function changeStatus(): Response {
        $data = input('get.');
        $validate = Validate::rule([
            'id|记录ID' => 'require',
            'uuid|用户标识' => 'require',
        ]);
        if (!$validate->check($data)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $joinStudent = AdminStudentParents::hasWhere('parent', function($query) use($data) {
                $query->where('uuid', $data['uuid']);
            })->where('admin_student_parents.id', $data['id'])->find();
        if (!$joinStudent) {
            return $this->buildFailed(ReturnCode::NOT_EXISTS, '记录不存在');
        }
        $joinStudent->is_delete = 1;
        $joinStudent->delete_time = time();
        if (!$joinStudent->save()) {
            return $this->buildFailed(ReturnCode::DB_SAVE_ERROR);
        }
        return $this->buildSuccess();
    }

    /**
     * @notes: 绑定设备信息
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author: speed
     */
    public function bindDeviceInfo(): Response {
        $data = input('get.');
        $validate = Validate::rule([
            'uuid|用户标识' => 'require',
        ]);
        if (!$validate->check($data)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $parent_data = AdminParentsData::hasWhere('parents', function($query) use($data) {
            $query->where('uuid', $data['uuid'])->where('is_delete', 0);
        })->whereIn('bind_device_status', '1,2')
            ->find();

        if (!$parent_data) {
            return $this->buildSuccess();
        }
        $device = $parent_data->visible(['last_login_device_id', 'last_login_device_name','last_bind_device_time', 'bind_device_status'])
            ->append(['status_text'])->toArray();
        return $this->buildSuccess($device);
    }

    /**
     * @notes: 绑定设备申请解绑
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author: speed
     */
    public function unbindDevice(): Response {
        $data = input('get.');
        $validate = Validate::rule([
            'uuid|用户标识' => 'require',
        ]);
        if (!$validate->check($data)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $parent_data = AdminParentsData::hasWhere('parents', function($query) use($data) {
            $query->where('uuid', $data['uuid'])->where('is_delete', 0);
        })->whereIn('bind_device_status', '1,2')->find();

        if (!$parent_data) {
            return $this->buildFailed(ReturnCode::NOT_EXISTS, '记录不存在或已解绑');
        }
        $parent_data->bind_device_status = 2;
        $parent_data->save();
        return $this->buildSuccess();
    }

    public function logout(): Response {
        $data = input('get.');
        $validate = Validate::rule([
            'uuid|用户标识' => 'require',
        ]);
        if (!$validate->check($data)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $parent = (new AdminParents())->where('uuid', $data['uuid'])->where('is_delete', 0)->find();
        if (!$parent) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '账号不存在');
        }
        // 删除记录
        $redis = PoolRedis::instance();
        $redis->delete('deviceUUID:staff'.$parent->uuid);
        $redis->delete('deviceUUID:staff'.$parent->id);
        return $this->buildSuccess([], '注销成功');
    }
}